package com.stiove.whwh.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stiove.whwh.dao.mapper.*;
import com.stiove.whwh.dao.pojo.*;
import com.stiove.whwh.service.ThreadService;
import com.stiove.whwh.service.TicketService;
import com.stiove.whwh.utils.OssUtils;
import com.stiove.whwh.utils.UserThreadLocal;
import com.stiove.whwh.vo.Env;
import com.stiove.whwh.vo.Result;
import com.stiove.whwh.vo.TicketImgVo;
import com.stiove.whwh.vo.TicketVo;
import com.stiove.whwh.vo.params.OrderParams;
import com.stiove.whwh.vo.params.TicketParams;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

@Data
@Service
public class TicketServiceImpl implements TicketService {

    @Autowired
    private TicketMapper ticketMapper;
    @Autowired
    private UserOrderMapper userOrderMapper;
    @Autowired
    private TicketImgMapper ticketImgMapper;
    @Autowired
    private TicketHotMapper ticketHotMapper;

    @Autowired
    private UserLikeMapper userLikeMapper;

    @Autowired
    private Env env;
    @Autowired
    private ThreadService threadService;






    /**
     * @param city
     * @param sort 1：价格降序 2：价格升序 3：开始时间近 4：开始时间远
     * @param status 1: 未开始 2已开场 3已结束
     * @return
     */
    @Override
    public Result getTicketList(String city ,int sort,int status,int page) {
        LambdaQueryWrapper<Ticket> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(Ticket::getDeleteTime);

        if (StringUtils.isBlank(city)) return new Result(Result.USER_ERROR,"请定位或选择地点");
        wrapper.eq(Ticket::getCity,city);

        switch (sort){
            case 1:
               wrapper.orderByDesc(Ticket::getPrice);
               break;
            case 2:
                wrapper.orderByAsc(Ticket::getPrice);
                break;
            case 3:
                wrapper.orderByAsc(Ticket::getStartTime);
                break;
            case 4:
                wrapper.orderByDesc(Ticket::getStartTime);
                break;
            default: wrapper.orderByDesc(Ticket::getUpdateTime);
            break;
        }

        switch (status){
            case 1:
               wrapper.gt(Ticket::getStartTime,System.currentTimeMillis());
               break;
            case 2:
                wrapper.lt(Ticket::getStartTime,System.currentTimeMillis()).gt(Ticket::getEndTime,System.currentTimeMillis());
                break;
            case 3:
                wrapper.lt(Ticket::getEndTime,System.currentTimeMillis());
                break;
            default:wrapper.gt(Ticket::getEndTime,System.currentTimeMillis());
            break;
        }

        if (page == 0) page = 1;
        Page<Ticket> pageNum = new Page<>(page, 10);
        Page<Ticket> ticketPage = ticketMapper.selectPage(pageNum, wrapper);
        if (ticketPage.getRecords() == null){
            return new Result(Result.SUCCESS,"cg");
        }

        ArrayList<TicketVo> ticketVo = ticketListCopy(ticketPage.getRecords());

        return new Result(Result.SUCCESS,"cg",ticketVo);
    }

    @Override
    public Result getTicketBannerList() {

        LambdaQueryWrapper<TicketHot> wrapper = Wrappers.lambdaQuery();
        wrapper.orderByDesc(TicketHot::getHot)
                .last("limit 4");

        List<TicketHot> ticketHots = ticketHotMapper.selectList(wrapper);
        if (ticketHots == null){
            return new Result(Result.SUCCESS,"cg");
        }
        ArrayList<TicketVo> ticketList = hotCopy(ticketHots);

        return new Result(Result.SUCCESS,"cg",ticketList);
    }

    @Override
    public Result searchTicketList(String input, int page) {
        LambdaQueryWrapper<Ticket> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(Ticket::getDeleteTime)
                .like(Ticket::getTitle,input);

        if (page == 0) page = 1;
        Page<Ticket> pageNum = new Page<>(page, 10);
        Page<Ticket> ticketPage = ticketMapper.selectPage(pageNum, wrapper);

        if (ticketPage.getRecords() == null){
            return new Result(Result.SUCCESS,"cg");
        }
        ArrayList<TicketVo> ticketVo = ticketListCopy(ticketPage.getRecords());

        return new Result(Result.SUCCESS,"cg",ticketVo);
    }

    @Override
    public Result getTicketInfo(int id) {
        LambdaQueryWrapper<Ticket> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(Ticket::getDeleteTime)
                .eq(Ticket::getId,id)
                .last("limit 1");
        Ticket ticket = ticketMapper.selectOne(wrapper);
        if (ticket == null){
            return new Result(Result.USER_ERROR,"无此ID信息");
        }
        TicketVo ticketVo = ticketCopy(ticket,1);

        threadService.updateViewCount(ticketHotMapper,ticketVo);
        if (userLikeMapper.getIsLike(UserThreadLocal.get().getId(),ticketVo.getId()) == null){
            ticketVo.setIs_like(false);
        }else {
            ticketVo.setIs_like(true);
        }

        return new Result(Result.SUCCESS,"cg",ticketVo);
    }

    @Override
    public Result getTicketByHot() {
        LambdaQueryWrapper<Ticket> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(Ticket::getDeleteTime);
        Integer count = ticketMapper.selectCount(wrapper);

        Random random = new Random();
        if (count>8){
            count = random.nextInt(count-8);
        }else{
            count = 0;
        }

        LambdaQueryWrapper<Ticket> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.isNull(Ticket::getDeleteTime).last("limit " + count + ",8 ");
        List<Ticket> tickets = ticketMapper.selectList(queryWrapper);

        ArrayList<TicketImgVo> ticketImgVos = new ArrayList<>();
        for (Ticket ticket : tickets) {
            TicketImgVo ticketImgVo = new TicketImgVo();
            BeanUtils.copyProperties(ticket,ticketImgVo);
            LambdaQueryWrapper<TicketImg> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.eq(TicketImg::getTicketId,ticket.getId()).last("limit 1");
            TicketImg ticketImg = ticketImgMapper.selectOne(lambdaQuery);
            if (ticketImg != null){
                ticketImgVo.setImgUrl(ticketImg.getImgUrl());
            }
            ticketImgVos.add(ticketImgVo);
        }

        return new Result(Result.SUCCESS,"cg",ticketImgVos);
    }

    @Override
    @Transactional
    public Result creatTicket(TicketParams ticketParams) {
        long time = System.currentTimeMillis();
        String objectName ="ticket/"+ time + ticketParams.getImg().getOriginalFilename();

        TicketImg ticketImg = new TicketImg();
        ticketImg.setImgUrl(env.bucket + objectName);
        ticketImg.setUpdateTime(time);

        Ticket ticket = new Ticket();
        ticket.setTitle(ticketParams.getTitle());
        ticket.setPrice(ticketParams.getPrice());
        ticket.setInfo(ticketParams.getInfo());
        ticket.setAddress(ticketParams.getAddress());
        ticket.setCity(ticketParams.getCity());
        ticket.setStartTime(ticketParams.getStartTime());
        ticket.setEndTime(ticketParams.getEndTime());
        ticket.setUpdateTime(time);

        OssUtils ossUtils = new OssUtils();
        try {
            ossUtils.upload(ticketParams.getImg().getInputStream(), objectName,env);
            ticketMapper.insert(ticket);
            System.out.println(ticket.getId());
            ticketImg.setTicketId(ticket.getId());
            ticketImgMapper.insert(ticketImg);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(Result.SERVER_ERROR,"失败");
        }

        return new Result(Result.SUCCESS,"成功");

    }

    @Override
    public Result likeTicket(int id){
        Long userId = UserThreadLocal.get().getId();
        UserLike like = new UserLike();
        like.setUpdateTime(System.currentTimeMillis());
        like.setIsLike(1);
        LambdaQueryWrapper<UserLike> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(UserLike::getDeleteTime).eq(UserLike::getUserId,userId).eq(UserLike::getTicketId,id);
        if(userLikeMapper.selectOne(wrapper)==null){
            like.setTicketId((long) id);
            like.setUserId(userId);
            userLikeMapper.insert(like);
        }else{
            userLikeMapper.update(like,wrapper);
        }
        return new Result(Result.SUCCESS,"成功",id);
    }

    @Override
    public Result getAdminTicket(int page) {
        LambdaQueryWrapper<Ticket> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(Ticket::getDeleteTime)
                .gt(Ticket::getEndTime,System.currentTimeMillis());

        if (page == 0) page = 1;
        Page<Ticket> pageNum = new Page<>(page, 20);
        Page<Ticket> ticketPage = ticketMapper.selectPage(pageNum, wrapper);
        if (ticketPage.getRecords() == null){
            return new Result(Result.SUCCESS,"cg");
        }

        ArrayList<TicketVo> ticketVo = ticketListCopy(ticketPage.getRecords());
        return new Result(Result.SUCCESS,"成功",ticketVo);
    }

    @Override
    @Transactional
    public Result delTicket(int id) {
        long time = System.currentTimeMillis();
        try {
            ticketMapper.delById(id,time);
            ticketImgMapper.deleteByTicketId(id,time);
            userLikeMapper.deleteByTicketId(id,time);
            userOrderMapper.deleteByTicketId(id,time);
        }catch (Exception e){
            return new Result(Result.SERVER_ERROR,"服务器错误",e.getMessage());
        }
        return new Result(Result.SUCCESS,"成功");
    }

    @Override
    public Result getLikeTicket(int page) {
        Long id = UserThreadLocal.get().getId();
        LambdaQueryWrapper<UserLike> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserLike::getUserId,id).isNull(UserLike::getDeleteTime);

        if (page == 0) page = 1;
        Page<UserLike> pageNum = new Page<>(page, 20);
        Page<UserLike> userLikePage = userLikeMapper.selectPage(pageNum, wrapper);
        if (userLikePage.getRecords() == null){
            return new Result(Result.SUCCESS,"cg");
        }

        List<UserLike> records = userLikePage.getRecords();

        ArrayList<TicketImgVo> ticketImgVos = new ArrayList<>();
        for (UserLike record : records) {
            TicketImgVo ticketImgVo = ticketMapper.selectTicketInfoById(record.getTicketId());
            ticketImgVos.add(ticketImgVo);
        }
        return new Result(Result.SUCCESS,"成功",ticketImgVos);
    }

    @Override
    public Result delLike(int id) {
        Long uid = UserThreadLocal.get().getId();
        try {
            userLikeMapper.deleteByUserId(id,uid,System.currentTimeMillis());
            return new Result(Result.SUCCESS,"成功");
        }catch (Exception e){
            return new Result(Result.SERVER_ERROR,"服务器错误",e.getMessage());
        }
    }

    private ArrayList<TicketVo> hotCopy(List<TicketHot> ticketHots) {
        ArrayList<TicketVo> ticketVos = new ArrayList<>();

        for (TicketHot ticketHot : ticketHots) {
            LambdaQueryWrapper<Ticket> wrapper = Wrappers.lambdaQuery();
            Ticket ticket = ticketMapper.selectOne(wrapper.eq(Ticket::getId, ticketHot.getTicketId()).last("limit 1"));
            TicketVo ticketVo = ticketCopy(ticket,0);
            ticketVo.setHot(ticketHot.getHot());
            ticketVos.add(ticketVo);
        }

        return ticketVos;
    }

    public ArrayList<TicketVo> ticketListCopy(List<Ticket> records) {
        ArrayList<TicketVo> ticketVoList = new ArrayList<>();
        for (Ticket record : records) {
            ticketVoList.add(ticketCopy(record,1));
        }

        return ticketVoList;
    }

    private TicketVo ticketCopy(Ticket record,int haveHot) {
        Result result = new Result();

        LambdaQueryWrapper<TicketImg> wrapperTicketImg = Wrappers.lambdaQuery();
        LambdaQueryWrapper<TicketHot> wrapperTicketHot = Wrappers.lambdaQuery();
        TicketVo ticketVo = new TicketVo();
        BeanUtils.copyProperties(record,ticketVo);
        ticketVo.setStartTime(result.switchTime(record.getStartTime()));
        ticketVo.setEndTime(result.switchTime(record.getEndTime()));

        wrapperTicketImg.isNull(TicketImg::getDeleteTime)
                .eq(TicketImg::getTicketId,record.getId())
                .select(TicketImg::getImgUrl)
                .last("limit 1");
        TicketImg ticketImg = ticketImgMapper.selectOne(wrapperTicketImg);
        if (ticketImg == null){
            ticketVo.setImgUrl(null);
        } else{
            ticketVo.setImgUrl(ticketImg.getImgUrl());
        }

        if (haveHot == 1){
            wrapperTicketHot.eq(TicketHot::getTicketId,record.getId())
                    .last("limit 1");
            TicketHot ticketHot = ticketHotMapper.selectOne(wrapperTicketHot);
            if (ticketHot == null){
                ticketVo.setHot(0);
            }else {
                ticketVo.setHot(ticketHot.getHot());
            }
        }

        return ticketVo;
    }
}
